package com.power.sifa.approve.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.plf.common.domain.YesNo;
import com.plf.core.base.model.Ha_attachment;
import com.plf.core.base.service.Ha_attachmentService;
import com.plf.core.common.service.BaseServiceImpl;
import com.power.sifa.approve.dao.Apl_thirdperDao;
import com.power.sifa.approve.model.Apl_admre_audit;
import com.power.sifa.approve.model.Apl_admreview;
import com.power.sifa.approve.model.Apl_thirdper;
import com.power.sifa.approve.model.pageInfo.Apl_thirdperPageInfo;
import com.power.sifa.approve.service.Apl_admre_auditService;
import com.power.sifa.approve.service.Apl_admreviewService;
import com.power.sifa.approve.service.Apl_thirdperService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 第三人业务层实现
 */
@Service
public class Apl_thirdperServiceImpl extends BaseServiceImpl implements Apl_thirdperService {

    @Autowired
    private Apl_thirdperDao dao;

    @Resource
    private Ha_attachmentService ha_attachmentService;

    @Autowired
    private Apl_admreviewService apl_admreviewService;

    @Autowired
    private Apl_admre_auditService apl_admre_auditService;


    @Override
    public Apl_thirdper getById(Serializable id) {
        return dao.findById(id).orElse(null);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdate(Apl_thirdper apl_thirdper) {
        // save 如果数据库不存在这条数据，就会执行保存（即将这条数据插入到数据库）；如果数据库存在这条数据，就会根据主键去更新这条数据
        if (apl_thirdper.getPrimaryKey() != null) {
            Apl_thirdper apl_thirdperfDb = dao.findById(apl_thirdper.getPrimaryKey()).orElse(null);
            if (apl_thirdperfDb != null) {
                BeanUtils.copyProperties(apl_thirdper, apl_thirdperfDb);
                dao.save(apl_thirdperfDb);
                this.updateProcessThirdName(apl_thirdper.getApplyid());
                return;
            }
        }
        // 获取当前最大的排序
        Integer sortNum = ObjectUtil.isNotEmpty(dao.queryMaxSotNumberApply(apl_thirdper.getApplyid())) ?
                dao.queryMaxSotNumberApply(apl_thirdper.getApplyid()) + 1 : 0;
        apl_thirdper.setId(apl_thirdper.getApplyid() + NanoIdUtils.randomNanoId());
        apl_thirdper.setSortnum(sortNum);
        dao.save(apl_thirdper);
        this.updateProcessThirdName(apl_thirdper.getApplyid());
    }

    /**
     * 更新主流程和子流程的记录数据
     *
     * @param applyid applyid
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateProcessThirdName(String applyid) {
        // 查询全部的第三人名称
        List<Apl_thirdper> thirdperList = dao.getByApplyid(applyid);
        String thirdName = "";
        if (CollectionUtil.isNotEmpty(thirdperList)) {
            List<String> thirdNameList = thirdperList.stream().filter(element -> ObjectUtil.isNotNull(element.getName())).map(Apl_thirdper::getName).collect(Collectors.toList());
            thirdName = CollectionUtil.isNotEmpty(thirdNameList) ? String.join("，", thirdNameList) : "";
        }
        // 更新主流程和子流程的记录数据
        if (StringUtils.isNotBlank(applyid)) {
            // 更新主流程和子流程的记录数据
            Apl_admreview admreview = apl_admreviewService.getById(applyid);
            admreview.setThirdname(thirdName);
            if (CollectionUtil.isNotEmpty(thirdperList)) {
                admreview.setIsthird(YesNo.YES);
            }
            apl_admreviewService.saveOrUpdate(admreview);
            List<Apl_admre_audit> admreAuditList = apl_admre_auditService.listAdmreAuditByApplyid(applyid);
            if (CollectionUtil.isNotEmpty(admreAuditList)) {
                // 第三人字段是thirdper
                String finalThirdName = thirdName;
                admreAuditList.stream().forEach(element -> {
                    element.setThirdper(finalThirdName);
                });
                apl_admre_auditService.saveAll(admreAuditList);
            }
        }
    }


    @Override
    public void removeById(Serializable id) {
        dao.deleteById(id);
    }

    @Override
    public Page<Apl_thirdper> findAll(Apl_thirdperPageInfo pageInfo) {
        //排序等定义
        Sort sort;
        if ("asc".equals(pageInfo.getOrder())) {
            sort = Sort.by(Sort.Direction.ASC, pageInfo.getSort());
        } else {
            sort = Sort.by(Sort.Direction.DESC, pageInfo.getSort());
        }
        //分页的定义
        Pageable pageable = PageRequest.of(pageInfo.getPageNumber() <= 1 ? 0 : pageInfo.getPageNumber() - 1, pageInfo.getPageSize(), sort);
        //查询条件
        Specification spec = this.createSpecification(pageInfo);
        Specification<Apl_thirdper> specification = (root, query, criteriaBuilder) -> query.where(
                criteriaBuilder.and(criteriaBuilder.and(criteriaBuilder.equal(root.get("saved"), YesNo.YES)))
        ).getRestriction();

        spec.and(specification);
        Page<Apl_thirdper> page = dao.findAll(spec, pageable);
        // 新增查询附件的信息
        if (CollectionUtil.isEmpty(page.getContent())) {
            return page;
        }
        getAttachFile(page.getContent(), Apl_thirdper::getFilecard, 0);
        getAttachFile(page.getContent(), Apl_thirdper::getDoccard, 1);
        getAttachFile(page.getContent(), Apl_thirdper::getThirdevidence, 2);
        return page;
    }

    public void getAttachFile(List<Apl_thirdper> thridList, Function<Apl_thirdper, String> function,
                              Integer type) {
        if (ObjectUtil.isNotNull(thridList) && CollectionUtil.isNotEmpty(thridList)) {
            Map<String, List<String>> attchMap = new HashMap<>();
            List<String> attchId = new ArrayList<>();
            thridList.stream().forEach(item -> {
                String attchid = function.apply(item);
                if (StringUtils.isNotEmpty(attchid)) {
                    List<String> attchList = Arrays.asList(attchid.split(","));
                    attchId.addAll(attchList);
                    attchMap.put(item.getId(), attchList);
                }
            });
            // 查询对应的附件数据
            Map<String, Ha_attachment> ha_attachmentMap = ha_attachmentService.getHa_attachmentsByIds(attchId);
            if (ObjectUtil.isNotNull(ha_attachmentMap)) {
                for (String id : attchMap.keySet()) {
                    List<Ha_attachment> fileLists = new ArrayList<>();
                    List<String> attchids = attchMap.get(id);
                    for (String attchid : attchids) {
                        fileLists.add(ha_attachmentMap.get(attchid));
                    }
                    thridList.stream().filter(item -> item.getId().equals(id)).findFirst().ifPresent(obj -> {
                        switch (type) {
                            case 0:
                                obj.setFilecardList(fileLists);
                                break;
                            case 1:
                                obj.setDoccardList(fileLists);
                                break;
                            case 2:
                                obj.setThirdEvidenceList(fileLists);
                                break;
                            default:
                                break;
                        }
                    });
                }
            }
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public void removeByIds(List<Integer> ids) {
        dao.removeByIds(ids);
    }

    @Override
    public List<Apl_thirdper> findAll() {
        return dao.findAll();
    }

    @Override
    public void saveAll(List<Apl_thirdper> list) {
        dao.saveAll(list);
    }

    @Override
    public List<Apl_thirdper> getThirdListByApplyid(String applyid) {
        Specification<Apl_thirdper> specification = (root, query, criteriaBuilder) -> query.where(
                criteriaBuilder.and(criteriaBuilder.equal(root.get("applyid"), applyid), criteriaBuilder.and(criteriaBuilder.equal(root.get("saved"), YesNo.YES)))
        ).getRestriction();
        return dao.findAll(specification);
    }

    @Override
    public Map<Integer, List<Apl_thirdper>> getThirdWithGroup(String applyid) {
        List<Apl_thirdper> thirdperList = this.getThirdListByApplyid(applyid);
        if (CollectionUtil.isEmpty(thirdperList)) {
            return null;
        }
        getAttachFile(thirdperList, Apl_thirdper::getFilecard, 0);
        getAttachFile(thirdperList, Apl_thirdper::getDoccard, 1);
        getAttachFile(thirdperList, Apl_thirdper::getThirdevidence, 2);
        return thirdperList.stream().collect(Collectors.groupingBy(Apl_thirdper::getType));
    }

    @Override
    public List<Apl_thirdper> searchByName(String name) {
        List<Map<String, Object>> cardNoList = dao.searchCardNoByName("%" + name + "%");
        if (CollectionUtil.isNotEmpty(cardNoList)) {
            // 按照名称去重
            Map<String, String> distictMap = new HashMap<>();
            for (Map<String, Object> cardMap : cardNoList) {
                String cardNo = (String) cardMap.get("cardNo");
                String id = (String) cardMap.get("id");
                distictMap.put(cardNo, id);
            }
            List<String> ids = new ArrayList<>();
            for (String key : distictMap.keySet()) {
                String id = distictMap.get(key).toString();
                ids.add(id);
            }
            return dao.getByIds(ids);
        }
        return Collections.emptyList();
    }

    /**
     * 查询未保存的第三人通过applyid
     */
    @Override
    public Map<Integer, List<Apl_thirdper>> getUnSaveThirdWithGroup(String applyid) {
        Specification<Apl_thirdper> specification = (root, query, criteriaBuilder) -> query.where(
                criteriaBuilder.and(criteriaBuilder.equal(root.get("applyid"), applyid), criteriaBuilder.and(criteriaBuilder.equal(root.get("saved"), YesNo.NO)))
        ).getRestriction();
        List<Apl_thirdper> thirdperList = dao.findAll(specification);
        if (CollectionUtil.isEmpty(thirdperList)) {
            return null;
        }
        getAttachFile(thirdperList, Apl_thirdper::getFilecard, 0);
        getAttachFile(thirdperList, Apl_thirdper::getDoccard, 1);
        getAttachFile(thirdperList, Apl_thirdper::getThirdevidence, 2);
        return thirdperList.stream().collect(Collectors.groupingBy(Apl_thirdper::getType));
    }

    @Override
    public void updateUnSaveThirder(String applyid) {
        this.dao.updateUnSaveThirder(applyid);
    }

    @Override
    public void removeUnSaveThirder(String applyid) {
        this.dao.removeUnSaveThirder(applyid);
    }

}
